﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

using NeuralNetwork;
using System.IO;

namespace Pruebas
{
    public class Salida : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Funciones[] RedNeural;
        Dictionary<double[], int>[] Test;

        SpriteFont texto;
        public Salida()
        {
            graphics = new GraphicsDeviceManager(this);
            this.graphics.PreferredBackBufferWidth = 900;
            this.graphics.PreferredBackBufferHeight = 570;
            Content.RootDirectory = "Content";
        }

        int[] Neuronas;
        RenderTarget2D screenshot;
        string[] File;

        protected override void Initialize()
        {

            //Mejor para Profe    500 ==> 7
            //Mejor para Profe   1000 ==> 9
            //Mejor para Profe   2000 ==> 10
            //Mejor para Nuestra  500 ==> 10
            //Mejor para Nuestra 1000 ==> 2
            //Mejor para Nuestra 2000 ==> 7
            Neuronas = new int[]{7,9,10,10,2,7};
            RedNeural = new Funciones[Neuronas.Length];
            File = new string[RedNeural.Length];
            File[0] = "datos_r6_n500.txt";
            File[1] = "datos_r6_n1000.txt";
            File[2] = "datos_r6_n2000.txt";
            File[3] = "Caso500.txt";
            File[4] = "Caso1000.txt";
            File[5] = "Caso2000.txt";

            for (int i = 0; i<Neuronas.Length ;++i )
                RedNeural[i] = new Funciones(3, Neuronas[i], 1,File[i]);

            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            texto = this.Content.Load<SpriteFont>("Imagenes/Fuente");
            screenshot = new RenderTarget2D(GraphicsDevice, 900, 570);


            Test = new Dictionary<double[], int>[RedNeural.Length + 1];

            string[] A = new string[2];
            A[0] = "Main";

            Test[0] = Validacion();
            for (int i = 0; i < RedNeural.Length; ++i )
            {
                A[1] = "Content/Grupo_Entrenamiento/" + File[i];
                Console.WriteLine("Entrenando Red de " + File[i] + " de "+ Neuronas[i]+ " Neuronas" );
                RedNeural[i].Training2(RedNeural[i].Entrada(A));
                Test[i + 1] = RedNeural[i].Testing(Test[0]);
                ScreenShot(i);
            }
        }


        protected override void UnloadContent()
        {
            screenshot.Dispose();
        }

        int Verif_Circ(double x, double y)
        {
            if (Math.Sqrt(Math.Pow(x - 10.0, 2.0) + Math.Pow(y - 10.0, 2.0)) <= 6)
                return 0;
            else
                return 1;
        }

        Dictionary<double[], int> Validacion()
        {
            Dictionary<double[], int> Test = new Dictionary<double[], int>();

            double dist = 20.0 / 100.0;
            for (int i = 0; i < 100; i++)
                for (int j = 0; j < 100; j++)
                {
                    double x = dist * i;
                    double y = dist * j;
                    double[] Tmp = { y, x };
                    Test.Add(Tmp, Verif_Circ(y, x));
                }
            return Test;

        }

        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
            {
                this.Exit();
            }

            base.Update(gameTime);
        }


        public void ScreenShot(int i)
        {

            int w = GraphicsDevice.PresentationParameters.BackBufferWidth;
            int h = GraphicsDevice.PresentationParameters.BackBufferHeight;

            //force a frame to be drawn (otherwise back buffer is empty)
            DrawRedNeural(i,new GameTime());

            //pull the picture from the buffer
            int[] backBuffer = new int[w * h];
            GraphicsDevice.GetBackBufferData(backBuffer);

            //copy into a texture
            Texture2D texture = new Texture2D(GraphicsDevice, w, h, false, GraphicsDevice.PresentationParameters.BackBufferFormat);
            texture.SetData(backBuffer);

            //save to disk
            Stream stream = System.IO.File.OpenWrite("screenshot_" + File[i] + ".png");
            texture.SaveAsPng(stream, w, h);
            stream.Close();

        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();
            spriteBatch.DrawString(texto, "Finalizado ", new Vector2(500, 500), Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }

        void DrawRedNeural(int i, GameTime gameTime)
        {
            int Scale = 2;
            int H = 2 * Scale;
            int W = 2 * Scale;

            Texture2D Textura = new Texture2D(graphics.GraphicsDevice, H, W);
            Color[] dataColor = new Color[W * H];
            for (int j = 0; j < W * H; ++j)
                dataColor[j] = Color.White;
            Textura.SetData(dataColor);


            spriteBatch.Begin();

            GraphicsDevice.Clear(Color.Black);
            spriteBatch.DrawString(texto, "Conjunto de entrenamiento: " + File[i], new Vector2(250, 10), Color.White);
            spriteBatch.DrawString(texto, "Objetivo", new Vector2(200, 50), Color.White);
            spriteBatch.DrawString(texto, Neuronas[i] + " Neuronas", new Vector2(620, 50), Color.White);


            foreach (var T in Test[0]) //Objetivo
                if (T.Value == 1)
                    spriteBatch.Draw(Textura, new Vector2(40 + (float)T.Key[0] * 10 * Scale , 80 + (float)T.Key[1] * 10 * Scale), Color.Blue);
                else
                    spriteBatch.Draw(Textura, new Vector2(40 + (float)T.Key[0] * 10 * Scale , 80 + (float)T.Key[1] * 10 * Scale), Color.Green);

            foreach (var T in Test[i + 1]) //Aproximado Red
                if (T.Value == 1)
                    spriteBatch.Draw(Textura, new Vector2(20 + (float)T.Key[0] * 10 * Scale + 450, 80 + (float)T.Key[1] * 10 * Scale), Color.Blue);
                else
                    spriteBatch.Draw(Textura, new Vector2(20 + (float)T.Key[0] * 10 * Scale + 450, 80 + (float)T.Key[1] * 10 * Scale), Color.Green);

            spriteBatch.DrawString(texto, "Numero de Iteraciones: " + RedNeural[i].Max_Iteracion, new Vector2(300, 520), Color.White);

            spriteBatch.End();
            base.Draw(gameTime);
        }

    }
}
